module hz
#(
parameter TIME_500MS =  25'd24999999, //0.5s计数值

parameter NONE = 18'd0,
parameter DO_LOW  = 18'd191693,
parameter RE_LOW  = 18'd171007,
parameter MI_LOW  = 18'd151977,
parameter FA_LOW  = 18'd143551,
parameter SO_LOW  = 18'd127769,
parameter LA_LOW  = 18'd113849,
parameter XI_LOW  = 18'd100472,
parameter DO_MID  = 17'd95846,
parameter RE_MID  = 17'd85503,
parameter MI_MID  = 17'd75988,
parameter FA_MID  = 17'd71776,
parameter SO_MID  = 16'd63884,
parameter LA_MID  = 16'd56925,
parameter XI_MID  = 16'd50236,
parameter DO_HIGH = 16'd47923,
parameter RE_HIGH = 16'd42752,
parameter MI_HIGH = 16'd37994,
parameter FA_HIGH = 16'd35888,
parameter SO_HIGH = 16'd31942,
parameter LA_HIGH = 16'd28462,
parameter XI_HIGH = 16'd25118

)
 (
 input wire sys_clk , //系统时钟,频率50MHz
 input wire sys_rst_n , //系统复位，低有效
 input wire volume_button, //音量键

 output reg beep, //输出蜂鸣器控制信号
 output reg[2:0] display_number,
 output reg led
 );

 ////
 //\* Parameter and Internal Signal \//
 ////

 //reg define
 reg [24:0] cnt ; //0.5s计数器
 reg [17:0] freq_cnt ; //音调计数器
 reg [4:0] cnt_500ms ; //0.5s个数计数
 reg [17:0] freq_data ; //音调分频计数值
 
 reg [2:0] volume_level;    // 3 bits to represent 7 volume levels (1 to 7)
reg volume_button_prev = 1'b0; // Previous state of the volume_button

 //wire define
 wire [16:0] duty_data ; //占空比计数值

 ////
 //\* Main Code \//
 ////

 //设置50％占空比：音阶分频计数值的一半即为占空比的高电平数
 //assign duty_data = freq_data >> 3'b111;

 //cnt:0.5s循环计数器
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 cnt <= 25'd0;
 else if(cnt == TIME_500MS )
 cnt <= 25'd0;
 else
 cnt <= cnt + 1'b1;

 //cnt_500ms：对500ms个数进行计数，每个音阶鸣叫时间0.5s，7个音节一循环
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 cnt_500ms <= 3'd0;
 else if(cnt == TIME_500MS && cnt_500ms == 27)
 cnt_500ms <= 3'd0;
 else if(cnt == TIME_500MS)
 cnt_500ms <= cnt_500ms + 1'b1;
 
 
 // Volume control state machine
//always @(posedge sys_clk or negedge sys_rst_n) begin
//    if (sys_rst_n == 1'b0) begin
//        volume_level <= 3'b001; // Initialize volume level to 1 (right shift by 1)
//        volume_button_prev <= 1'b0;
//    end else begin
//        if (volume_button && !volume_button_prev) begin // Button press detected
//            volume_level <= volume_level + 3'b001;
//            if (volume_level == 3'b111) begin // If volume_level is 7, then wrap around
//                volume_level <= 3'b001;
//            end
//        end
//        volume_button_prev <= volume_button; // Update previous button state
//    end
//end
always @(posedge sys_clk or negedge sys_rst_n) begin
    if (sys_rst_n == 1'b0) begin
        volume_level <= 3'b001; // Initialize volume level to 1 (right shift by 1)
        volume_button_prev <= 1'b0;
    end else begin
        if (volume_button && !volume_button_prev) begin // Button press detected
            case (volume_level)
                3'b001: volume_level <= 3'b010; // Transition from level 1 to level 2
                3'b010: volume_level <= 3'b011; // Transition from level 2 to level 3
                3'b011: volume_level <= 3'b100; // Transition from level 3 to level 4
                3'b100: volume_level <= 3'b101; // Transition from level 4 to level 5
                3'b101: volume_level <= 3'b110; // Transition from level 5 to level 6
                3'b110: volume_level <= 3'b111; // Transition from level 6 to level 7
                3'b111: volume_level <= 3'b001; // Transition from level 7 back to level 1
                default: volume_level <= 3'b001; // Any unexpected state defaults back to level 1
            endcase
        end
        volume_button_prev <= volume_button; // Update previous button state
    end
end



 //不同时间鸣叫不同的音阶
 always@(posedge sys_clk or negedge sys_rst_n) begin
 if(sys_rst_n == 1'b0) begin
 freq_data <= DO_LOW;
 display_number <= 3'b000;
 end

case(cnt_500ms)
    0: begin
        freq_data <= NONE;
        display_number <= 3'b000;
		  led <= 0;
    end
    //happy birthday to you 1
    1: begin
        freq_data <= SO_LOW;
        display_number <= 3'b101;  // 显示5
		  led <= 1;
    end
    2: begin
        freq_data <= LA_MID;
        display_number <= 3'b110;  // 显示6
		  led <= 1;
    end
    3: begin
        freq_data <= SO_MID;
        display_number <= 3'b101;  // 显示5
		  led <= 1;
    end
    4: begin
        freq_data <= DO_HIGH;
        display_number <= 3'b001;  // 显示1
		  led <= 1;
    end
    5: begin
        freq_data <= XI_MID;
        display_number <= 3'b111;  // 显示7
		  led <= 1;
    end
    6: begin
        freq_data <= NONE;
        display_number <= 3'b000;  // 显示0
		  led <= 1;
    end
    //happy birthday to you 2
    7: begin
        freq_data <= SO_LOW;
        display_number <= 3'b101;  // 显示5
		  led <= 1;
    end
    8: begin
        freq_data <= LA_MID;
        display_number <= 3'b110;  // 显示6
		  led <= 1;
    end
    9: begin
        freq_data <= SO_MID;
        display_number <= 3'b101;  // 显示5
		  led <= 1;
    end
    10: begin
        freq_data <= RE_HIGH;
        display_number <= 3'b010;  // 显示2
		  led <= 1;
    end
    11: begin
        freq_data <= DO_HIGH;
        display_number <= 3'b001;  // 显示1
		  led <= 1;
    end
    12: begin
        freq_data <= NONE;
        display_number <= 3'b000;  // 显示0
		  led <= 1;
    end
    //happy birthday to you 3
    13: begin
        freq_data <= SO_LOW;
        display_number <= 3'b101;  // 显示5
		  led <= 1;
    end
    14: begin
        freq_data <= SO_HIGH;
        display_number <= 3'b101;  // 显示5
		  led <= 1;
    end
    15: begin
        freq_data <= MI_HIGH;
        display_number <= 3'b011;  // 显示3
		  led <= 1;
    end
    16: begin
        freq_data <= DO_HIGH;
        display_number <= 3'b001;  // 显示1
		  led <= 1;
    end
    17: begin
        freq_data <= XI_MID;
        display_number <= 3'b111;  // 显示7
		  led <= 1;
    end
    18: begin
        freq_data <= LA_MID;
        display_number <= 3'b110;  // 显示6
		  led <= 1;
    end
    //happy birthday to you 4
    19: begin
        freq_data <= FA_HIGH;
        display_number <= 3'b100;  // 显示4
		  led <= 1;
    end
    20: begin
        freq_data <= MI_HIGH;
        display_number <= 3'b011;  // 显示3
		  led <= 1;
    end
    21: begin
        freq_data <= DO_HIGH;
        display_number <= 3'b001;  // 显示1
		  led <= 1;
    end
    22: begin
        freq_data <= RE_HIGH;
        display_number <= 3'b010;  // 显示2
		  led <= 1;
    end
    23: begin
        freq_data <= DO_HIGH;
        display_number <= 3'b001;  // 显示1
		  led <= 1;
    end
    24: begin
        freq_data <= NONE;
        display_number <= 3'b000;  // 显示0
		  led <= 1;
    end


	 
	 default: begin
        freq_data <= NONE;
        display_number <= 3'b000;  // 默认显示0
		  led <= 0;
    end
endcase
end
 //freq_cnt：当计数到音阶计数值或跳转到下一音阶时，开始重新计数
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 freq_cnt <= 18'd0;
 else if(freq_cnt == freq_data || cnt == TIME_500MS)
 freq_cnt <= 18'd0;
 else
 freq_cnt <= freq_cnt + 1'b1;

 //beep：输出蜂鸣器波形
  assign duty_data = freq_data >> volume_level;
 // generate beep signal
always @(posedge sys_clk or negedge sys_rst_n) begin
    if (sys_rst_n == 1'b0) begin
        beep <= 1'b0;
    end else if (freq_cnt >= duty_data) begin
        beep <= 1'b0;
    end else begin
        beep <= 1'b1;
    end
end

 endmodule
//module hz (
//    input wire sys_clk,
//    input wire sys_rst_n,
//    input wire volume_button,
//    output reg beep,
//    output reg[2:0] display_number
//);
//
//    parameter TIME_500MS = 25'd24999999;
//    parameter NUM_NOTES = 21;
//    
//  reg [24:0] timer_cnt;
//reg [17:0] freq_cnt;
//reg [4:0] note_idx = 0;
//
//reg [2:0] volume_level = 3'b001;
//reg volume_button_prev = 1'b0;
//
//// 初始化音符数据
//reg [17:0] note_data [0:20]; // 21个音符
//initial begin
//    note_data[0]  = 18'd191693;
//    note_data[1]  = 18'd171007;
//    note_data[2]  = 18'd151977;
//    note_data[3]  = 18'd143551;
//    note_data[4]  = 18'd127769;
//    note_data[5]  = 18'd113849;
//    note_data[6]  = 18'd100472;
//    note_data[7]  = 17'd95846;
//    note_data[8]  = 17'd85503;
//    note_data[9]  = 17'd75988;
//    note_data[10] = 17'd71776;
//    note_data[11] = 16'd63884;
//    note_data[12] = 16'd56925;
//    note_data[13] = 16'd50236;
//    note_data[14] = 16'd47923;
//    note_data[15] = 16'd42752;
//    note_data[16] = 16'd37994;
//    note_data[17] = 16'd35888;
//    note_data[18] = 16'd31942;
//    note_data[19] = 16'd28462;
//    note_data[20] = 16'd25118;
//end
//
//// 控制蜂鸣器波形
//always @(posedge sys_clk or negedge sys_rst_n) begin
//    if (sys_rst_n == 1'b0) begin
//        beep <= 1'b0;
//    end else if (freq_cnt >= (note_data[note_idx] >> volume_level)) begin
//        beep <= 1'b0;
//    end else begin
//        beep <= 1'b1;
//    end
//end
//    
//    // Timer logic
//always @(posedge sys_clk or negedge sys_rst_n) begin
//    if (sys_rst_n == 1'b0) begin
//        timer_cnt <= 25'd0;
//    end else if (timer_cnt == TIME_500MS) begin
//        timer_cnt <= 25'd0;
//        note_idx <= (note_idx + 1) % NUM_NOTES;
//    end else begin
//        timer_cnt <= timer_cnt + 1'b1;
//    end
//end
//
//// Frequency counter logic
//always @(posedge sys_clk or negedge sys_rst_n) begin
//    if (sys_rst_n == 1'b0) begin
//        freq_cnt <= 18'd0;
//    end else if (freq_cnt == note_data[note_idx] >> volume_level || timer_cnt == TIME_500MS) begin
//        freq_cnt <= 18'd0;
//    end else begin
//        freq_cnt <= freq_cnt + 1'b1;
//    end
//end
//
//// Volume control state machine
//always @(posedge sys_clk or negedge sys_rst_n) begin
//    if (sys_rst_n == 1'b0) begin
//        volume_level <= 3'b001;
//        volume_button_prev <= 1'b0;
//    end else begin
//        if (volume_button && !volume_button_prev) begin
//            volume_level <= volume_level + 3'b001;
//            if (volume_level == 3'b111) begin
//                volume_level <= 3'b001;
//            end
//        end
//        volume_button_prev <= volume_button;
//    end
//end
//
//// Display logic
//always @(posedge sys_clk or negedge sys_rst_n) begin
//    if (sys_rst_n == 1'b0) begin
//        display_number <= 3'b000;
//    end else begin
//        display_number <= note_idx[2:0];
//    end
//end
//
//    
//    
//    
//endmodule

